import copy
import json
from typing import List
from typing import Union
from apis import api_routes
from flask import abort, g, request, jsonify
from security.decoration import certification
from models.product.routes import Routes
from models.facility.facility import Facility
from security.security import decode_jwt
from public.local import datetime_type
from models.users.users import Users
from models.product.aircraft import Aircraft
from models.product.repairs import Repairs


@api_routes.route("/template", methods=["POST"])
@certification(auth=True, role=None)
def func_template_post_api():
    """
    添加返工路径，完成API开发
    http://127.0.0.1:8080/api/template
    Content-Type=application/json
    methods=["POST"]
    {
    "name"          string      ****    工艺路线名称
    "aircraft_id"   int         机种ID
    "routes"        array[json] ****    生产加工工艺路线  [{"ft_ids": [1]}, {"ft_ids": [2, 3]},{"ft_ids": [4]}, ....]
    }
    :return:
        {'status': 400, 'msg': '客户端发送请求异常'}
        {'status': 4000, 'msg': "名称已存在，禁止重复添加"}
        {'status': 4001, 'msg': "工序参数数据类型类型错误"}
        {'status': 4002, 'msg': "工序参数验证设备不能为空"}
        {'status': 4003, 'msg': "工序参数没有找到要绑定设备"}
        {'status': 4004, 'msg': "设备没有绑定PLC, 无法交互，禁止添加"}
        {'status': 4005, 'msg': "同一工序禁止添加重复设备"}
        {'status': 4006, 'msg': "相隔工序不能存在同一种设备"}
        {'status': 200, 'msg': "添加返工模板路线成功"}
    ---
    tags:
      - 返工模板管理
    """

    data: dict = request.get_json()
    name: str = data.get("name")
    routes: list = data.get("routes")
    aircraft_id: int = data.get("aircraft_id")

    if name is None or (isinstance(routes, list) is False) or aircraft_id is None:
        abort(400)
    db_repair: Union[Repairs, None] = g.session.query(Repairs).filter(Repairs.name == name).first()
    if db_repair is not None:
        return jsonify({'status': 4000, 'msg': "名称已存在，禁止重复添加!"})

    db_aircraft: Union[Aircraft, None] = g.session.query(Aircraft).filter(Aircraft.id == aircraft_id).first()
    if db_aircraft is None:
        return jsonify({'status': 4000, 'msg': "未找到机种"})

    # 解析routes数据，判断是否合法性
    temp_routes = []
    for index, itr in enumerate(routes):
        if (not isinstance(itr, dict)) or (not isinstance(itr.get("ft_ids"), list)):
            return jsonify({'status': 4001, 'msg': "工序参数数据类型类型错误 "})
        ft_ids: list = itr.get("ft_ids")
        if len(ft_ids) == 0:
            return jsonify({'status': 4002, 'msg': "工序参数验证设备不能为空 "})
        for itr2 in ft_ids:
            db_ft: Union[Facility, None] = g.session.query(Facility).filter(Facility.id == itr2).first()
            if db_ft is None:
                return jsonify({'status': 4003, 'msg': "工序参数没有找到要绑定设备 "})
            if db_ft.uuid4 is None:
                return jsonify({'status': 4004, 'msg': "设备没有绑定PLC, 无法交互，禁止添加 "})
        if len(set(ft_ids)) != len(ft_ids):
            return jsonify({'status': 4005, 'msg': "同一工序禁止添加重复设备"})
        temp_routes.append(ft_ids)

    for itr in range(1, len(temp_routes)):
        before: list = temp_routes[itr - 1]
        now_date: list = temp_routes[itr]
        list3 = []
        for item in before:
            if item in now_date:
                list3.append(item)
        if len(list3) != 0:
            return jsonify({'status': 4006, 'msg': "相隔工序不能存在同一种设备 "})

    g.session.add(Repairs(
        name=name,
        route=json.dumps({"data": routes}),
        time=datetime_type(),
        aircraft_id=aircraft_id,
    ))
    g.session.commit()
    return jsonify({'status': 200, 'msg': "添加返工模板路线成功"})


@api_routes.route("/template", methods=["GET"])
@certification(auth=True, role=None)
def func_template_get_api():
    """
    查询工艺路线详细信息，完成API开发
    http://127.0.0.1:8080/api/template
    Content-Type=application/x-www-form-urlencoded
    methods=["GET"]
    {
    "index"     int      ****  第几页，默认为1
    "size"      int      ****  每页数据多少, 默认每页10条数据
    }
    :return:
    ---
    tags:
      - 返工模板管理
    """
    index = request.args.get("index", default=1, type=int)
    size = request.args.get("size", default=10, type=int)

    count = g.session.query(Repairs).order_by(Repairs.id).count()
    page = int((count / size) + 1) if (count / size) > int(count / size) else int(count / size)
    db_data: List[Repairs] = g.session.query(Repairs).order_by(Repairs.id).offset((index - 1) * size).limit(size).all()

    resp: list = []
    for index, itr in enumerate(db_data):

        list_rts: list = []
        route: dict = json.loads(itr.route)
        routes: list = route.get("data")
        for sequence, rts in enumerate(routes):
            data_rts: list = []
            data_rts.clear()
            db_rout: list = rts.get("ft_ids")
            for _, rt in enumerate(db_rout):
                db_ft: Facility = g.session.query(Facility).filter(Facility.id == rt).first()
                data_rts.append({
                    "serials": db_ft.serials,
                    "name": db_ft.name,
                    "facility_id": db_ft.id,
                    "sequence": sequence + 1,
                })
            list_rts.append(data_rts)

        resp.append({
            "template_id": itr.id,
            "routes": copy.deepcopy(list_rts),
            "name": itr.name,
            "time": itr.time.strftime("%Y-%m-%d %H:%M:%S") if itr.time else None
        })
    doc: dict = {
        "template_id": "对应数据库ID",
        "name": "返工模板路线名称",
        "time": "路径添加时间",
        "routes": [{
            "name": "设备名称",
            "serials": "设备编码",
            "sequence": "加工顺序",
            "facility_id": "设备ID(对应数据库)"
        }]
    }
    return jsonify({'status': 200, 'data': resp, "index": index, "size": size, "total": count, "pages": page, "doc": doc})


@api_routes.route("/template/all", methods=["GET"])
@certification(auth=True, role=None)
def func_template_all_get_api():
    """
    查询全部返工模板信息，完成API开发
    http://127.0.0.1:8080/api/template/all
    Content-Type=application/x-www-form-urlencoded
    methods=["GET"]
    {
    "aircraft_id", int  机种ID
    }
    :return:
    ---
    tags:
      - 返工模板管理
    """
    aircraft_id: int = request.args.get("aircraft_id", default=0, type=int)
    resp: list = []
    db_data: List[Repairs] = g.session.query(Repairs).order_by(Repairs.id).all()
    if aircraft_id > 0:
        db_data: List[Repairs] = g.session.query(Repairs).filter(Repairs.aircraft_id == aircraft_id).order_by(Repairs.id).all()
    for itr in db_data:
        resp.append({
            "key": itr.id,
            "value": itr.name
        })
    return jsonify({'status': 200, 'data': resp})


@api_routes.route("/template", methods=["PUT"])
@certification(auth=True, role=None)
def func_template_put_api():
    """
    更新工艺路线详细信息, 完成API开发
    http://127.0.0.1:8080/api/template
    Content-Type=application/json
    methods=["PUT"]
    {
    "template_id"      int      ****    对应路劲数据库ID
    "name"          string      ****    路线名字
    "routes"        array[json] ****    生产加工工艺路线  [{"ft_ids": [1]}, {"ft_ids": [2, 3]},{"ft_ids": [4]}, ....]
    }
    :return:
        {'status': 4000, 'msg': "没有找到路径工艺"}
        {'status': 4001, 'msg': "工艺名字已存在，禁止修改"}
        {'status': 4002, 'msg': "生产加工路径参数错误"}
        {'status': 4003, 'msg': "工序参数没有找到要绑定设备"}
        {'status': 4004, 'msg': "设备没有绑定PLC, 无法交互"}
        {'status': 4005, 'msg': "同一工序禁止添加重复设备"}
        {'status': 4006, 'msg': "相隔工序不能存在同一种设备！"}
        {'status': 200, 'msg': "更新返工模板信息成功"}
    ---
    tags:
      - 返工模板管理
    """
    data: dict = request.get_json()
    template_id: int = data.get("template_id")
    name: Union[str, None] = data.get("name")
    routes: Union[list, None] = data.get("routes")

    if template_id is None:
        abort(400)
    db_repair: Union[Repairs, None] = g.session.query(Repairs).filter(Repairs.id == template_id).first()
    if db_repair is None:
        return jsonify({'status': 4000, 'msg': "没有找到路径工艺"})

    if name != db_repair.name and name is not None:
        db_repair2: Union[Repairs, None] = g.session.query(Repairs).filter(Repairs.name == name).first()
        if db_repair2 is not None:
            return jsonify({'status': 4001, 'msg': "返工模板名字已存在，禁止修改"})
        db_repair.name = name

    if routes is not None:
        temp_routes: list = []
        if not isinstance(routes, list):
            g.session.rollback()
            return jsonify({'status': 4002, 'msg': "生产加工路径参数错误!"})

        for _, itr in enumerate(routes):
            if (not isinstance(itr, dict)) or (not isinstance(itr.get("ft_ids"), list)):
                return jsonify({'status': 4001, 'msg': "工序参数数据类型类型错误!"})
            ft_ids: list = itr.get("ft_ids")
            if len(ft_ids) == 0:
                return jsonify({'status': 4002, 'msg': "工序参数验证设备不能为空值!"})

            for itr2 in ft_ids:
                db_ft: Union[Facility, None] = g.session.query(Facility).filter(Facility.id == itr2).first()
                if db_ft is None:
                    return jsonify({'status': 4003, 'msg': "工序参数没有找到要绑定设备!"})
                if db_ft.uuid4 is None:
                    return jsonify({'status': 4004, 'msg': "设备没有绑定PLC, 无法交互!"})
            if len(set(ft_ids)) != len(ft_ids):
                return jsonify({'status': 4005, 'msg': "同一工序禁止添加重复设备!"})
            temp_routes.append(ft_ids)

        for itr in range(1, len(temp_routes)):
            before: list = temp_routes[itr - 1]
            now_date: list = temp_routes[itr]
            list3 = []
            for item in before:
                if item in now_date:
                    list3.append(item)
            if len(list3) != 0:
                return jsonify({'status': 4006, 'msg': "相隔工序不能存在同一种设备!!"})
        db_repair.route = json.dumps({"data": routes})

    g.session.commit()
    return jsonify({'status': 200, 'msg': "更新返工模板信息成功"})


@api_routes.route("/template", methods=["DELETE"])
@certification(auth=True, role=None)
def func_template_delete_api():
    """
    删除返修工艺路径
    http://127.0.0.1:8080/api/template
    Content-Type=application/json
    methods=["DELETE"]
    {
    "template_id"      int     ****    对应路劲数据库ID
    }
    :return:
        {'status': 4000, 'msg': "没有找到路径工艺"}
        {'status': 4001, 'msg': "已绑定产品，无法删除，先删除产品"}
        {'status': 200, 'msg': "删除成功"}
    ---
    tags:
      - 返工模板管理
    """
    data: dict = request.get_json()
    template_id: int = data.get("template_id")
    if not template_id:
        abort(400)

    db_repair: Union[Repairs, None] = g.session.query(Repairs).filter(Repairs.id == template_id).first()
    if db_repair is None:
        return jsonify({'status': 4000, 'msg': "没有找到返修工艺"})

    g.session.query(Repairs).filter(Repairs.id == template_id).delete()
    g.session.commit()
    return jsonify({'status': 200, 'msg': "删除成功"})
